/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.kotlin.components

import kotlin.Boolean
import kotlin.Int
import kotlin.String
import kotlin.Unit
import org.apache.camel.kotlin.CamelDslMarker
import org.apache.camel.kotlin.UriDsl

/**
 * Execute commands on remote hosts using SSH.
 */
public fun UriDsl.ssh(i: SshUriDsl.() -> Unit) {
  SshUriDsl(this).apply(i)
}

@CamelDslMarker
public class SshUriDsl(
  it: UriDsl,
) {
  private val it: UriDsl

  init {
    this.it = it
    this.it.component("ssh")
  }

  private var host: String = ""

  private var port: String = ""

  /**
   * Sets the hostname of the remote SSH server.
   */
  public fun host(host: String) {
    this.host = host
    it.url("$host:$port")
  }

  /**
   * Sets the port number for the remote SSH server.
   */
  public fun port(port: String) {
    this.port = port
    it.url("$host:$port")
  }

  /**
   * Sets the port number for the remote SSH server.
   */
  public fun port(port: Int) {
    this.port = port.toString()
    it.url("$host:$port")
  }

  /**
   * Specifies whether a connection to an unknown host should fail or not. This value is only
   * checked when the property knownHosts is set.
   */
  public fun failOnUnknownHost(failOnUnknownHost: String) {
    it.property("failOnUnknownHost", failOnUnknownHost)
  }

  /**
   * Specifies whether a connection to an unknown host should fail or not. This value is only
   * checked when the property knownHosts is set.
   */
  public fun failOnUnknownHost(failOnUnknownHost: Boolean) {
    it.property("failOnUnknownHost", failOnUnknownHost.toString())
  }

  /**
   * Sets the resource path for a known_hosts file
   */
  public fun knownHostsResource(knownHostsResource: String) {
    it.property("knownHostsResource", knownHostsResource)
  }

  /**
   * Sets the timeout in milliseconds to wait in establishing the remote SSH server connection.
   * Defaults to 30000 milliseconds.
   */
  public fun timeout(timeout: String) {
    it.property("timeout", timeout)
  }

  /**
   * Sets the timeout in milliseconds to wait in establishing the remote SSH server connection.
   * Defaults to 30000 milliseconds.
   */
  public fun timeout(timeout: Int) {
    it.property("timeout", timeout.toString())
  }

  /**
   * Sets the command string to send to the remote SSH server during every poll cycle. Only works
   * with camel-ssh component being used as a consumer, i.e. from(ssh://...) You may need to end your
   * command with a newline, and that must be URL encoded %0A
   */
  public fun pollCommand(pollCommand: String) {
    it.property("pollCommand", pollCommand)
  }

  /**
   * If the polling consumer did not poll any files, you can enable this option to send an empty
   * message (no body) instead.
   */
  public fun sendEmptyMessageWhenIdle(sendEmptyMessageWhenIdle: String) {
    it.property("sendEmptyMessageWhenIdle", sendEmptyMessageWhenIdle)
  }

  /**
   * If the polling consumer did not poll any files, you can enable this option to send an empty
   * message (no body) instead.
   */
  public fun sendEmptyMessageWhenIdle(sendEmptyMessageWhenIdle: Boolean) {
    it.property("sendEmptyMessageWhenIdle", sendEmptyMessageWhenIdle.toString())
  }

  /**
   * Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions
   * (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the
   * likes, will now be processed as a message and handled by the routing Error Handler. Important:
   * This is only possible if the 3rd party component allows Camel to be alerted if an exception was
   * thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not
   * possible. In other situations we may improve the Camel component to hook into the 3rd party
   * component and make this possible for future releases. By default the consumer will use the
   * org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or
   * ERROR level and ignored.
   */
  public fun bridgeErrorHandler(bridgeErrorHandler: String) {
    it.property("bridgeErrorHandler", bridgeErrorHandler)
  }

  /**
   * Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions
   * (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the
   * likes, will now be processed as a message and handled by the routing Error Handler. Important:
   * This is only possible if the 3rd party component allows Camel to be alerted if an exception was
   * thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not
   * possible. In other situations we may improve the Camel component to hook into the 3rd party
   * component and make this possible for future releases. By default the consumer will use the
   * org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or
   * ERROR level and ignored.
   */
  public fun bridgeErrorHandler(bridgeErrorHandler: Boolean) {
    it.property("bridgeErrorHandler", bridgeErrorHandler.toString())
  }

  /**
   * To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is
   * enabled then this option is not in use. By default the consumer will deal with exceptions, that
   * will be logged at WARN or ERROR level and ignored.
   */
  public fun exceptionHandler(exceptionHandler: String) {
    it.property("exceptionHandler", exceptionHandler)
  }

  /**
   * Sets the exchange pattern when the consumer creates an exchange.
   */
  public fun exchangePattern(exchangePattern: String) {
    it.property("exchangePattern", exchangePattern)
  }

  /**
   * A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom
   * implementation to control error handling usually occurred during the poll operation before an
   * Exchange have been created and being routed in Camel.
   */
  public fun pollStrategy(pollStrategy: String) {
    it.property("pollStrategy", pollStrategy)
  }

  /**
   * Whether the producer should be started lazy (on the first message). By starting lazy you can
   * use this to allow CamelContext and routes to startup in situations where a producer may otherwise
   * fail during starting and cause the route to fail being started. By deferring this startup to be
   * lazy then the startup failure can be handled during routing messages via Camel's routing error
   * handlers. Beware that when the first message is processed then creating and starting the producer
   * may take a little time and prolong the total processing time of the processing.
   */
  public fun lazyStartProducer(lazyStartProducer: String) {
    it.property("lazyStartProducer", lazyStartProducer)
  }

  /**
   * Whether the producer should be started lazy (on the first message). By starting lazy you can
   * use this to allow CamelContext and routes to startup in situations where a producer may otherwise
   * fail during starting and cause the route to fail being started. By deferring this startup to be
   * lazy then the startup failure can be handled during routing messages via Camel's routing error
   * handlers. Beware that when the first message is processed then creating and starting the producer
   * may take a little time and prolong the total processing time of the processing.
   */
  public fun lazyStartProducer(lazyStartProducer: Boolean) {
    it.property("lazyStartProducer", lazyStartProducer.toString())
  }

  /**
   * Sets the channel type to pass to the Channel as part of command execution. Defaults to exec.
   */
  public fun channelType(channelType: String) {
    it.property("channelType", channelType)
  }

  /**
   * Instance of ClientBuilder used by the producer or consumer to create a new SshClient
   */
  public fun clientBuilder(clientBuilder: String) {
    it.property("clientBuilder", clientBuilder)
  }

  /**
   * Whether to use compression, and if so which.
   */
  public fun compressions(compressions: String) {
    it.property("compressions", compressions)
  }

  /**
   * Sets the shellPrompt to be dropped when response is read after command execution
   */
  public fun shellPrompt(shellPrompt: String) {
    it.property("shellPrompt", shellPrompt)
  }

  /**
   * Sets the sleep period in milliseconds to wait reading response from shell prompt. Defaults to
   * 100 milliseconds.
   */
  public fun sleepForShellPrompt(sleepForShellPrompt: String) {
    it.property("sleepForShellPrompt", sleepForShellPrompt)
  }

  /**
   * Sets the sleep period in milliseconds to wait reading response from shell prompt. Defaults to
   * 100 milliseconds.
   */
  public fun sleepForShellPrompt(sleepForShellPrompt: Int) {
    it.property("sleepForShellPrompt", sleepForShellPrompt.toString())
  }

  /**
   * The number of subsequent error polls (failed due some error) that should happen before the
   * backoffMultipler should kick-in.
   */
  public fun backoffErrorThreshold(backoffErrorThreshold: String) {
    it.property("backoffErrorThreshold", backoffErrorThreshold)
  }

  /**
   * The number of subsequent error polls (failed due some error) that should happen before the
   * backoffMultipler should kick-in.
   */
  public fun backoffErrorThreshold(backoffErrorThreshold: Int) {
    it.property("backoffErrorThreshold", backoffErrorThreshold.toString())
  }

  /**
   * The number of subsequent idle polls that should happen before the backoffMultipler should
   * kick-in.
   */
  public fun backoffIdleThreshold(backoffIdleThreshold: String) {
    it.property("backoffIdleThreshold", backoffIdleThreshold)
  }

  /**
   * The number of subsequent idle polls that should happen before the backoffMultipler should
   * kick-in.
   */
  public fun backoffIdleThreshold(backoffIdleThreshold: Int) {
    it.property("backoffIdleThreshold", backoffIdleThreshold.toString())
  }

  /**
   * To let the scheduled polling consumer backoff if there has been a number of subsequent
   * idles/errors in a row. The multiplier is then the number of polls that will be skipped before the
   * next actual attempt is happening again. When this option is in use then backoffIdleThreshold
   * and/or backoffErrorThreshold must also be configured.
   */
  public fun backoffMultiplier(backoffMultiplier: String) {
    it.property("backoffMultiplier", backoffMultiplier)
  }

  /**
   * To let the scheduled polling consumer backoff if there has been a number of subsequent
   * idles/errors in a row. The multiplier is then the number of polls that will be skipped before the
   * next actual attempt is happening again. When this option is in use then backoffIdleThreshold
   * and/or backoffErrorThreshold must also be configured.
   */
  public fun backoffMultiplier(backoffMultiplier: Int) {
    it.property("backoffMultiplier", backoffMultiplier.toString())
  }

  /**
   * Milliseconds before the next poll.
   */
  public fun delay(delay: String) {
    it.property("delay", delay)
  }

  /**
   * Milliseconds before the next poll.
   */
  public fun delay(delay: Int) {
    it.property("delay", delay.toString())
  }

  /**
   * If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the
   * previous run polled 1 or more messages.
   */
  public fun greedy(greedy: String) {
    it.property("greedy", greedy)
  }

  /**
   * If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the
   * previous run polled 1 or more messages.
   */
  public fun greedy(greedy: Boolean) {
    it.property("greedy", greedy.toString())
  }

  /**
   * Milliseconds before the first poll starts.
   */
  public fun initialDelay(initialDelay: String) {
    it.property("initialDelay", initialDelay)
  }

  /**
   * Milliseconds before the first poll starts.
   */
  public fun initialDelay(initialDelay: Int) {
    it.property("initialDelay", initialDelay.toString())
  }

  /**
   * Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only
   * fire once. If you set it to 5, it will only fire five times. A value of zero or negative means
   * fire forever.
   */
  public fun repeatCount(repeatCount: String) {
    it.property("repeatCount", repeatCount)
  }

  /**
   * Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only
   * fire once. If you set it to 5, it will only fire five times. A value of zero or negative means
   * fire forever.
   */
  public fun repeatCount(repeatCount: Int) {
    it.property("repeatCount", repeatCount.toString())
  }

  /**
   * The consumer logs a start/complete log line when it polls. This option allows you to configure
   * the logging level for that.
   */
  public fun runLoggingLevel(runLoggingLevel: String) {
    it.property("runLoggingLevel", runLoggingLevel)
  }

  /**
   * Allows for configuring a custom/shared thread pool to use for the consumer. By default each
   * consumer has its own single threaded thread pool.
   */
  public fun scheduledExecutorService(scheduledExecutorService: String) {
    it.property("scheduledExecutorService", scheduledExecutorService)
  }

  /**
   * To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or
   * quartz for built in scheduler
   */
  public fun scheduler(scheduler: String) {
    it.property("scheduler", scheduler)
  }

  /**
   * To configure additional properties when using a custom scheduler or any of the Quartz, Spring
   * based scheduler.
   */
  public fun schedulerProperties(schedulerProperties: String) {
    it.property("schedulerProperties", schedulerProperties)
  }

  /**
   * Whether the scheduler should be auto started.
   */
  public fun startScheduler(startScheduler: String) {
    it.property("startScheduler", startScheduler)
  }

  /**
   * Whether the scheduler should be auto started.
   */
  public fun startScheduler(startScheduler: Boolean) {
    it.property("startScheduler", startScheduler.toString())
  }

  /**
   * Time unit for initialDelay and delay options.
   */
  public fun timeUnit(timeUnit: String) {
    it.property("timeUnit", timeUnit)
  }

  /**
   * Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details.
   */
  public fun useFixedDelay(useFixedDelay: String) {
    it.property("useFixedDelay", useFixedDelay)
  }

  /**
   * Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details.
   */
  public fun useFixedDelay(useFixedDelay: Boolean) {
    it.property("useFixedDelay", useFixedDelay.toString())
  }

  /**
   * Sets the resource path of the certificate to use for Authentication. Will use
   * ResourceHelperKeyPairProvider to resolve file based certificate, and depends on keyType setting.
   */
  public fun certResource(certResource: String) {
    it.property("certResource", certResource)
  }

  /**
   * Sets the password to use in loading certResource, if certResource is an encrypted key.
   */
  public fun certResourcePassword(certResourcePassword: String) {
    it.property("certResourcePassword", certResourcePassword)
  }

  /**
   * Comma-separated list of allowed/supported ciphers in their order of preference.
   */
  public fun ciphers(ciphers: String) {
    it.property("ciphers", ciphers)
  }

  /**
   * Comma-separated list of allowed/supported key exchange algorithms in their order of preference.
   */
  public fun kex(kex: String) {
    it.property("kex", kex)
  }

  /**
   * Sets the KeyPairProvider reference to use when connecting using Certificates to the remote SSH
   * Server.
   */
  public fun keyPairProvider(keyPairProvider: String) {
    it.property("keyPairProvider", keyPairProvider)
  }

  /**
   * Sets the key type to pass to the KeyPairProvider as part of authentication.
   * KeyPairProvider.loadKey(...) will be passed this value. From Camel 3.0.0 / 2.25.0, by default
   * Camel will select the first available KeyPair that is loaded. Prior to this, a KeyType of
   * 'ssh-rsa' was enforced by default.
   */
  public fun keyType(keyType: String) {
    it.property("keyType", keyType)
  }

  /**
   * Comma-separated list of allowed/supported message authentication code algorithms in their order
   * of preference. The MAC algorithm is used for data integrity protection.
   */
  public fun macs(macs: String) {
    it.property("macs", macs)
  }

  /**
   * Sets the password to use in connecting to remote SSH server. Requires keyPairProvider to be set
   * to null.
   */
  public fun password(password: String) {
    it.property("password", password)
  }

  /**
   * Comma-separated list of allowed/supported signature algorithms in their order of preference.
   */
  public fun signatures(signatures: String) {
    it.property("signatures", signatures)
  }

  /**
   * Sets the username to use in logging into the remote SSH server.
   */
  public fun username(username: String) {
    it.property("username", username)
  }
}
